From baa7c435ce647615853c5b67cb543408e1de6f2e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 8 Aug 2006 10:17:42 +0100 Subject: [PATCH] [PCI] back: New virtual pci backend: slot This backend use a slot per pci device. Contrary to vpci two functions from one slot appear as two slots. This is useful on ia64 because it doesn't scan functions > 0 if function 0 does not exist. Signed-off-by: Tristan Gingold --- buildconfigs/linux-defconfig_xen0_ia64 | 3 +- buildconfigs/linux-defconfig_xen0_x86_32 | 1 + buildconfigs/linux-defconfig_xen0_x86_64 | 1 + buildconfigs/linux-defconfig_xen_ia64 | 3 +- buildconfigs/linux-defconfig_xen_x86_32 | 1 + buildconfigs/linux-defconfig_xen_x86_64 | 1 + linux-2.6-xen-sparse/drivers/xen/Kconfig | 11 +- .../drivers/xen/pciback/Makefile | 1 + .../drivers/xen/pciback/slot.c | 151 ++++++++++++++++++ 9 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 linux-2.6-xen-sparse/drivers/xen/pciback/slot.c diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index cd2008f9da..51379834a6 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -1533,8 +1533,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=y -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y # CONFIG_XEN_PCIDEV_BE_DEBUG is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32 index 3280f54f2c..8cd6a5e503 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_32 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 @@ -1320,6 +1320,7 @@ CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_BLKDEV_TAP=y diff --git a/buildconfigs/linux-defconfig_xen0_x86_64 b/buildconfigs/linux-defconfig_xen0_x86_64 index c219cd7f3c..05c6fed107 100644 --- a/buildconfigs/linux-defconfig_xen0_x86_64 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 @@ -1261,6 +1261,7 @@ CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_BLKDEV_TAP=y diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index 8ce5402772..a5eca9a8ad 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -1539,8 +1539,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=y -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y # CONFIG_XEN_PCIDEV_BE_DEBUG is not set # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32 index 286e47d71e..5c7e66550b 100644 --- a/buildconfigs/linux-defconfig_xen_x86_32 +++ b/buildconfigs/linux-defconfig_xen_x86_32 @@ -3021,6 +3021,7 @@ CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_XEN_PCIDEV_BACKEND_VPCI=y # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_BLKDEV_TAP=y diff --git a/buildconfigs/linux-defconfig_xen_x86_64 b/buildconfigs/linux-defconfig_xen_x86_64 index 6299af3b5e..019531708b 100644 --- a/buildconfigs/linux-defconfig_xen_x86_64 +++ b/buildconfigs/linux-defconfig_xen_x86_64 @@ -2853,6 +2853,7 @@ CONFIG_XEN_BACKEND=y CONFIG_XEN_PCIDEV_BACKEND=m # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set CONFIG_XEN_BLKDEV_BACKEND=y CONFIG_XEN_BLKDEV_TAP=y diff --git a/linux-2.6-xen-sparse/drivers/xen/Kconfig b/linux-2.6-xen-sparse/drivers/xen/Kconfig index b8a9479927..da25eeeaa2 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig @@ -117,7 +117,7 @@ config XEN_PCIDEV_BACKEND_VPCI This PCI Backend hides the true PCI topology and makes the frontend think there is a single PCI bus with only the exported devices on it. For example, a device at 03:05.0 will be re-assigned to 00:00.0. A - second device at 02:1a.0 will be re-assigned to 00:01.0. + second device at 02:1a.1 will be re-assigned to 00:01.1. config XEN_PCIDEV_BACKEND_PASS bool "Passthrough" @@ -129,6 +129,15 @@ config XEN_PCIDEV_BACKEND_PASS which depend on finding their hardward in certain bus/slot locations. +config XEN_PCIDEV_BACKEND_SLOT + bool "Slot" + ---help--- + This PCI Backend hides the true PCI topology and makes the frontend + think there is a single PCI bus with only the exported devices on it. + Contrary to the virtual PCI backend, a function becomes a new slot. + For example, a device at 03:05.2 will be re-assigned to 00:00.0. A + second device at 02:1a.1 will be re-assigned to 00:01.0. + endchoice config XEN_PCIDEV_BE_DEBUG diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile index b1d009d4ef..c7185fb7c8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile @@ -7,6 +7,7 @@ pciback-y += conf_space.o conf_space_header.o \ conf_space_capability_pm.o \ conf_space_quirks.o pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o +pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y) diff --git a/linux-2.6-xen-sparse/drivers/xen/pciback/slot.c b/linux-2.6-xen-sparse/drivers/xen/pciback/slot.c new file mode 100644 index 0000000000..09293fc68e --- /dev/null +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/slot.c @@ -0,0 +1,151 @@ +/* + * PCI Backend - Provides a Virtual PCI bus (with real devices) + * to the frontend + * + * Author: Ryan Wilson (vpci.c) + * Author: Tristan Gingold , from vpci.c + */ + +#include +#include +#include +#include +#include "pciback.h" + +/* There are at most 32 slots in a pci bus. */ +#define PCI_SLOT_MAX 32 + +#define PCI_BUS_NBR 2 + +struct slot_dev_data { + /* Access to dev_list must be protected by lock */ + struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX]; + spinlock_t lock; +}; + +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev, + unsigned int domain, unsigned int bus, + unsigned int devfn) +{ + struct pci_dev *dev = NULL; + struct slot_dev_data *slot_dev = pdev->pci_dev_data; + unsigned long flags; + + if (domain != 0 || PCI_FUNC(devfn) != 0) + return NULL; + + if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR) + return NULL; + + spin_lock_irqsave(&slot_dev->lock, flags); + dev = slot_dev->slots[bus][PCI_SLOT(devfn)]; + spin_unlock_irqrestore(&slot_dev->lock, flags); + + return dev; +} + +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) +{ + int err = 0, slot, bus; + struct slot_dev_data *slot_dev = pdev->pci_dev_data; + unsigned long flags; + + if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) { + err = -EFAULT; + xenbus_dev_fatal(pdev->xdev, err, + "Can't export bridges on the virtual PCI bus"); + goto out; + } + + spin_lock_irqsave(&slot_dev->lock, flags); + + /* Assign to a new slot on the virtual PCI bus */ + for (bus = 0; bus < PCI_BUS_NBR; bus++) + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + if (slot_dev->slots[bus][slot] == NULL) { + printk(KERN_INFO + "pciback: slot: %s: assign to virtual slot %d, bus %d\n", + pci_name(dev), slot, bus); + slot_dev->slots[bus][slot] = dev; + goto unlock; + } + } + + err = -ENOMEM; + xenbus_dev_fatal(pdev->xdev, err, + "No more space on root virtual PCI bus"); + + unlock: + spin_unlock_irqrestore(&slot_dev->lock, flags); + out: + return err; +} + +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev) +{ + int slot, bus; + struct slot_dev_data *slot_dev = pdev->pci_dev_data; + struct pci_dev *found_dev = NULL; + unsigned long flags; + + spin_lock_irqsave(&slot_dev->lock, flags); + + for (bus = 0; bus < PCI_BUS_NBR; bus++) + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + if (slot_dev->slots[bus][slot] == dev) { + slot_dev->slots[bus][slot] = NULL; + found_dev = dev; + goto out; + } + } + + out: + spin_unlock_irqrestore(&slot_dev->lock, flags); + + if (found_dev) + pcistub_put_pci_dev(found_dev); +} + +int pciback_init_devices(struct pciback_device *pdev) +{ + int slot, bus; + struct slot_dev_data *slot_dev; + + slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL); + if (!slot_dev) + return -ENOMEM; + + spin_lock_init(&slot_dev->lock); + + for (bus = 0; bus < PCI_BUS_NBR; bus++) + for (slot = 0; slot < PCI_SLOT_MAX; slot++) + slot_dev->slots[bus][slot] = NULL; + + pdev->pci_dev_data = slot_dev; + + return 0; +} + +int pciback_publish_pci_roots(struct pciback_device *pdev, + publish_pci_root_cb publish_cb) +{ + /* The Virtual PCI bus has only one root */ + return publish_cb(pdev, 0, 0); +} + +void pciback_release_devices(struct pciback_device *pdev) +{ + int slot, bus; + struct slot_dev_data *slot_dev = pdev->pci_dev_data; + struct pci_dev *dev; + + for (bus = 0; bus < PCI_BUS_NBR; bus++) + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + dev = slot_dev->slots[bus][slot]; + if (dev != NULL) + pcistub_put_pci_dev(dev); + } + + kfree(slot_dev); + pdev->pci_dev_data = NULL; +} -- 2.30.2